#pragma once
#include <iostream>
#include <string>
#include<memory>
using namespace std;

// 实现了三种智能指针
namespace my_stl
{

    template <class T>
    class auto_ptr
    {
        typedef auto_ptr<T> self;

    public:
        // 构造函数
        auto_ptr(T *ptr) : _ptr(ptr)
        {
        }
        ~auto_ptr()
        {
            if (_ptr)
            {
                cout << "delete" << _ptr << endl;
                delete _ptr;
                _ptr = nullptr;
            }
        }
        // 拷贝构造,移交管理权
        auto_ptr(auto_ptr<T> &au)
            : _ptr(au._ptr)
        {
            au._ptr = nullptr;
        }
        // 赋值运算符重载
        auto_ptr<T> &operator=(auto_ptr<T> &aut)
        {
            _ptr = aut._ptr;
            aut._ptr = nullptr;
            return *this;
        }
        T &operator*()
        {
            return *_ptr;
        }
        T *operator->()
        {
            return _ptr;
        }
        T *get()
        {
            return _ptr;
        }

    private:
        T *_ptr;
    };

    template <class T>
    class unique_ptr
    {
    public:
        // 构造函数
        unique_ptr(T *ptr) : _ptr(ptr)
        {
        }
        ~unique_ptr()
        {
            if (_ptr)
            {
                cout << "delete" << _ptr << endl;
                delete _ptr;
                _ptr = nullptr;
            }
        }
        // 防止拷贝
        // 方法一：使用关键字delete
        // 方法二：自己在类中声明并实现什么都不干的拷贝构造和赋值运算符重载
        unique_ptr(const unique_ptr<T> &q) = delete;
        unique_ptr<T> &operator=(const unique<T> &sp) = delete;
        T &operator*()
        {
            return *_ptr;
        }
        T *operator->()
        {
            return _ptr;
        }
        T *get()
        {
            return _ptr;
        }

    private:
        T *_ptr;
    };

    template <class t>
    class shared_ptr
    {
    public:
        void release()
        {
            if (--(*_count) == 0 && _ptr)
            {
                cout << "delete" << _ptr << endl;
                delete _ptr;
                _ptr = nullptr;
                delete _count;
                _count = nullptr;
            }
        }
        shared_ptr(t *ptr)
            : _ptr(ptr), _count(new int(1))
        {
        }
        ~shared_ptr()
        {
            release();
        }
        t &operator*()
        {
            return *_ptr;
        }
        t *operator->()
        {
            return _ptr;
        }
        t *get()
        {
            return _ptr;
        }
        shared_ptr(const shared_ptr<t> &sp)
            : _ptr(sp._ptr), _count(sp._count)
        {
            (*_count)++;
        }
        // 赋值运算符重载
        shared_ptr<t> &operator=(const shared_ptr<t> &sp)
        {
            // if (this != &sp)
            if (_ptr != sp._ptr)
            {
                release();
                _ptr = sp._ptr;
                _count = sp._count;
                ++(*_count);
            }
            return *this;
        }

    private:
        t *_ptr;
        int *_count;
    };

    template <class T>
    class myweak_ptr
    {
        myweak_ptr()
            : _ptr(nullptr)
        {
        }
        myweak_ptr(const std::shared_ptr<T> &sp)
            : _ptr(sp.get())
        {
        }
        myweak_ptr<T> &operator=(const std::shared_ptr<T> &sp)
        {
            if (_ptr != sp.get())
            {
                _ptr = sp.get();
            }
            return *this;
        }

    private:
        T *_ptr;
    };
}